home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / System / asyncioppc / source / async_ppc.c next >
Encoding:
C/C++ Source or Header  |  2001-06-19  |  12.8 KB  |  527 lines

  1. #include <clib/dos_protos.h>
  2. #include <clib/exec_protos.h>
  3. #include <clib/powerpc_protos.h>
  4. #include <libraries/asyncio.h>
  5. #include <exec/memory.h>
  6. #include <string.h>
  7.  
  8. #define D_S(type,name) char a_##name[ sizeof(type)+3]; type *name=(type *)((LONG)(a_##name+3)&~3);
  9.  
  10. #ifndef MIN
  11. #define MIN(a,b) ((a)<(b)?(a):(b))
  12. #endif
  13.  
  14. static void copymem(UBYTE *s,UBYTE *d,ULONG len)
  15. {
  16. ULONG l=len&3;
  17. len-=l;
  18. while(l--) *(d++)=*(s++);
  19. while(len)
  20.     {
  21.     *(((long *)d)++)=*(((long *)s)++);
  22.     len-=4;
  23.     }
  24. }
  25.  
  26. /*
  27. IMPORTANT:
  28. You might wonder why the hell there are these SPrintF calls ?
  29. I don't know why but the lib simply doesn't work without these
  30. dummy calls.
  31. Please DO NOT remove them. I have tested it a thousand times. It simply
  32. locks up when removing the SPrintF calls.
  33. The problem only occurs in write-mode !
  34. If you have any idea, why this happens, give me a hint.
  35. Email to: achimste@gmx.de
  36. */
  37.  
  38. static void AS_SendPacket(struct AsyncFile *file,APTR arg2)
  39. {
  40. file->af_Packet.sp_Pkt.dp_Port=&file->af_PacketPort;
  41. file->af_Packet.sp_Pkt.dp_Arg2=(LONG)arg2;
  42. SPrintF(0,0);
  43. PutMsg(file->af_Handler,&file->af_Packet.sp_Msg);
  44. SPrintF(0,0);
  45. file->af_PacketPending=TRUE;
  46. }
  47.  
  48. static long AS_WaitPacket(struct AsyncFile *file)
  49. {
  50. long bytes;
  51. if(file->af_PacketPending)
  52.     {
  53.     while(1)
  54.         {
  55.         file->af_PacketPort.mp_Flags=PA_SIGNAL;
  56.         RemovePPC((struct Node *)WaitPort(&file->af_PacketPort));
  57.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  58.         file->af_PacketPending=FALSE;
  59.         bytes=file->af_Packet.sp_Pkt.dp_Res1;
  60.         if(bytes>=0) return bytes;
  61.         if(ErrorReport(file->af_Packet.sp_Pkt.dp_Res2,REPORT_STREAM,file->af_File,0)) return -1;
  62.         AS_SendPacket(file,file->af_Buffers[file->af_ReadMode?file->af_CurrentBuf:1-file->af_CurrentBuf]);
  63.         }
  64.     }
  65. SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
  66. return file->af_Packet.sp_Pkt.dp_Res1;
  67. }
  68.  
  69. static void AS_RecordSyncFailure(struct AsyncFile *file)
  70. {
  71. file->af_LastRes1=file->af_Packet.sp_Pkt.dp_Res1;
  72. file->af_LastBytesLeft=file->af_BytesLeft;
  73. file->af_Packet.sp_Pkt.dp_Res1=-1;
  74. file->af_Packet.sp_Pkt.dp_Res2=IoErr();
  75. file->af_BytesLeft=0;
  76. }
  77.  
  78. static void AS_RequeuePacket(AsyncFile *file)
  79. {
  80. AddHeadPPC(&file->af_PacketPort.mp_MsgList,&file->af_Packet.sp_Msg.mn_Node);
  81. file->af_PacketPending=TRUE;
  82. }
  83.  
  84. struct AsyncFile *AS_OpenAsyncFH(BPTR handle,LONG mode,LONG bufferSize,ULONG closeIt)
  85. {
  86. FileHandle *fh;
  87. AsyncFile *file=0;
  88. BPTR lock=0;
  89. LONG blockSize,blockSize2;
  90. D_S(struct InfoData,infoData);
  91. if(mode==MODE_READ)
  92.     {
  93.     if(handle) lock=DupLockFromFH(handle);
  94.     }
  95. else
  96.     {
  97.     if(mode==MODE_APPEND)
  98.         {
  99.         if(handle)
  100.             {
  101.             if(Seek(handle,0,OFFSET_END)<0)
  102.                 {
  103.                 if(closeIt) Close(handle);
  104.                 handle=0;
  105.                 }
  106.             }
  107.         }
  108.     if(handle) lock=ParentOfFH(handle);
  109.     }
  110. if(handle)
  111.     {
  112.     blockSize=512;
  113.     blockSize2=1024;
  114.     if(lock)
  115.         {
  116.         if(Info(lock,infoData))
  117.             {
  118.             blockSize=infoData->id_BytesPerBlock;
  119.             blockSize2=blockSize*2;
  120.             bufferSize=((bufferSize+blockSize2-1)/blockSize2)*blockSize2;
  121.             }
  122.         UnLock(lock);
  123.         }
  124.     for(;;)
  125.         {
  126.         if(file=AllocVecPPC(sizeof(AsyncFile)+bufferSize+15,MEMF_PUBLIC,0)) break;
  127.         else
  128.             {
  129.             if(bufferSize>blockSize2) bufferSize-=blockSize2;
  130.             else break;
  131.             }
  132.         }
  133.     if(file)
  134.         {
  135.         file->af_File=handle;
  136.         file->af_ReadMode=(mode==MODE_READ);
  137.         file->af_BlockSize=blockSize;
  138.         file->af_CloseFH=closeIt;
  139.         fh=(FileHandle *)BADDR(file->af_File);
  140.         file->af_Handler=fh->fh_Type;
  141.         file->af_BufferSize=(ULONG)bufferSize/2;
  142.         file->af_Buffers[0]=(UBYTE *)(((ULONG)file+sizeof(AsyncFile)+15)&0xfffffff0);
  143.         file->af_Buffers[1]=file->af_Buffers[0]+file->af_BufferSize;
  144.         file->af_CurrentBuf=0;
  145.         file->af_SeekOffset=0;
  146.         file->af_PacketPending=FALSE;
  147.         file->af_SeekPastEOF=FALSE;
  148.         file->af_PacketPort.mp_MsgList.lh_Head=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
  149.         file->af_PacketPort.mp_MsgList.lh_Tail=0;
  150.         file->af_PacketPort.mp_MsgList.lh_TailPred=(struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
  151.         file->af_PacketPort.mp_Node.ln_Type=NT_MSGPORT;
  152.         file->af_PacketPort.mp_Node.ln_Name=0;
  153.         file->af_PacketPort.mp_Flags=PA_IGNORE;
  154.         file->af_PacketPort.mp_SigBit=SIGB_SINGLE;
  155.         file->af_PacketPort.mp_SigTask=FindTask(0);
  156.         file->af_Packet.sp_Pkt.dp_Link=&file->af_Packet.sp_Msg;
  157.         file->af_Packet.sp_Pkt.dp_Arg1=fh->fh_Arg1;
  158.         file->af_Packet.sp_Pkt.dp_Arg3=file->af_BufferSize;
  159.         file->af_Packet.sp_Pkt.dp_Res1=0;
  160.         file->af_Packet.sp_Pkt.dp_Res2=0;
  161.         file->af_Packet.sp_Msg.mn_Node.ln_Name=(STRPTR)&file->af_Packet.sp_Pkt;
  162.         file->af_Packet.sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
  163.         file->af_Packet.sp_Msg.mn_Length=sizeof(struct StandardPacket);
  164.         if(mode==MODE_READ)
  165.             {
  166.             file->af_Packet.sp_Pkt.dp_Type=ACTION_READ;
  167.             file->af_BytesLeft=0;
  168.             file->af_Offset=file->af_Buffers[1];
  169.             if(file->af_Handler) AS_SendPacket(file,file->af_Buffers[0]);
  170.             }
  171.         else
  172.             {
  173.             file->af_Packet.sp_Pkt.dp_Type=ACTION_WRITE;
  174.             file->af_BytesLeft=file->af_BufferSize;
  175.             file->af_Offset=file->af_Buffers[0];
  176.             }
  177.         }
  178.     else
  179.         {
  180.         if(closeIt) Close(handle);
  181.         }
  182.     }
  183. return file;
  184. }
  185.  
  186. struct AsyncFile * __saveds OpenAsyncPPC(struct AsyncIOBase *base,STRPTR fileName,LONG mode,LONG bufferSize)
  187. {
  188. static const ULONG PrivateOpenModes[]={MODE_OLDFILE,MODE_NEWFILE,MODE_READWRITE};
  189. BPTR handle;
  190. AsyncFile *file=0;
  191. if(handle=Open(fileName,PrivateOpenModes[mode]))
  192.     {
  193.     if(!(file=AS_OpenAsyncFH(handle,mode,bufferSize,TRUE))) Close(handle);
  194.     }
  195. return file;
  196. }
  197.  
  198. struct AsyncFile * __saveds OpenAsyncFromFHPPC(struct AsyncIOBase *base,BPTR handle,LONG mode,LONG bufferSize)
  199. {
  200. return AS_OpenAsyncFH(handle,mode,bufferSize,FALSE);
  201. }
  202.  
  203. LONG __saveds CloseAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file)
  204. {
  205. LONG result;
  206. if(file)
  207.     {
  208.     result=AS_WaitPacket(file);
  209.     if(result>=0)
  210.         {
  211.         if(!file->af_ReadMode)
  212.             {
  213.             if(file->af_BufferSize>file->af_BytesLeft)
  214.                 {
  215.                 result=Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft);
  216.                 }
  217.             }
  218.         }
  219.     if(file->af_CloseFH) Close(file->af_File);
  220.     FreeVecPPC(file);
  221.     }
  222. else result=-1;
  223. return result;
  224. }
  225.  
  226. LONG __saveds ReadAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  227. {
  228. LONG totalBytes=0;
  229. LONG bytesArrived;
  230. while(numBytes>file->af_BytesLeft)
  231.     {
  232.     copymem(file->af_Offset,buffer,file->af_BytesLeft);
  233.     numBytes-=file->af_BytesLeft;
  234.     buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  235.     totalBytes+=file->af_BytesLeft;
  236.     file->af_BytesLeft=0;
  237.     bytesArrived=AS_WaitPacket(file);
  238.     if(bytesArrived<=0)
  239.         {
  240.         if(bytesArrived==0) return(totalBytes);
  241.         return -1;
  242.         }
  243.     AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  244.     if(file->af_SeekOffset>bytesArrived) file->af_SeekOffset=bytesArrived;
  245.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+file->af_SeekOffset;
  246.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  247.     file->af_BytesLeft=bytesArrived-file->af_SeekOffset;
  248.     file->af_SeekOffset=0;
  249.     }
  250. copymem(file->af_Offset,buffer,numBytes);
  251. file->af_BytesLeft-=numBytes;
  252. file->af_Offset+=numBytes;
  253. return totalBytes+numBytes;
  254. }
  255.  
  256. LONG __saveds PeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  257. {
  258. if(!file->af_BytesLeft)
  259.     {
  260.     LONG bytes;
  261.     if((bytes=ReadAsyncPPC(base,file,&bytes,1))<=0) return bytes;
  262.     --file->af_Offset;
  263.     ++file->af_BytesLeft;
  264.     }
  265. numBytes=MIN(numBytes,file->af_BytesLeft);
  266. copymem(file->af_Offset,buffer,numBytes);
  267. return numBytes;
  268. }
  269.  
  270. LONG __saveds ReadCharAsyncPPC(struct AsyncIOBase *base,AsyncFile *file)
  271. {
  272. UBYTE    ch;
  273. if(file->af_BytesLeft)
  274.     {
  275.     ch=*file->af_Offset;
  276.     --file->af_BytesLeft;
  277.     ++file->af_Offset;
  278.     return ch;
  279.     }
  280. return (ReadAsyncPPC(base,file,&ch,1)>0)?ch:-1;
  281. }
  282.  
  283. STRPTR __saveds FGetsLenAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes,LONG *len)
  284. {
  285. UBYTE *p;
  286. LONG    length=0;
  287. p=(UBYTE *)buf;
  288. if(--numBytes<=0) return 0;
  289. while(TRUE)
  290.     {
  291.     UBYTE *ptr;
  292.     LONG i,count;
  293.     ptr=(UBYTE *)file->af_Offset;
  294.     if(count=file->af_BytesLeft)
  295.         {
  296.         count=MIN(count,numBytes);
  297.         for(i=0;(i<count)&&(*ptr!='\n');++i) *p++=*ptr++;
  298.         length+=i;
  299.         if(i<count)
  300.             {
  301.             *p++='\n';
  302.             ++i;
  303.             length+=1;
  304.             }
  305.         file->af_BytesLeft-=i;
  306.         file->af_Offset+=i;
  307.         if((i>=numBytes)||(*(p-1)=='\n')) break;
  308.         numBytes-=i;
  309.         }
  310.     if(ReadAsyncPPC(base,file,p,1)<1) break;
  311.     --numBytes;
  312.     ++length;
  313.     if(*p++=='\n') break;
  314.     }
  315. *p='\0';
  316. *len=length;
  317. return (p==(UBYTE *)buf)?0:buf;
  318. }
  319.  
  320. STRPTR __saveds FGetsAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR buf,LONG numBytes)
  321. {
  322. LONG len;
  323. return FGetsLenAsyncPPC(base,file,buf,numBytes,&len);
  324. }
  325.  
  326. LONG __saveds ReadLineAsyncPPC(struct AsyncIOBase *base,AsyncFile *file,APTR buffer,LONG bufSize)
  327. {
  328. LONG    len;
  329. if(FGetsLenAsyncPPC(base,file,buffer,bufSize,&len))
  330.     {
  331.     UBYTE *end;
  332.     end=((UBYTE *)buffer)+len-1;
  333.     if(*end!='\n')
  334.         {
  335.         UBYTE    ch=0;
  336.         while(TRUE)
  337.             {
  338.             UBYTE *ptr;
  339.             LONG i,count;
  340.             ptr=(UBYTE *)file->af_Offset;
  341.             if(count=file->af_BytesLeft)
  342.                 {
  343.                 for(i=0;(i<count)&&(*ptr!='\n');++i,++ptr);
  344.                 if(i<count)
  345.                     {
  346.                     ch='\n';
  347.                     ++i;
  348.                     }
  349.                 file->af_BytesLeft-=i;
  350.                 file->af_Offset+=i;
  351.                 if(i<count) break;
  352.                 }
  353.             if(ReadAsyncPPC(base,file,&ch,1)<1) break;
  354.             if(ch=='\n') break;
  355.             }
  356.         if(ch=='\n')
  357.             {
  358.             *end++='\n';
  359.             *end='\0';
  360.             }
  361.         }
  362.     }
  363. return len;
  364. }
  365.  
  366. static __saveds ULONG GetFileSize(AsyncFile *file,LONG *size)
  367. {
  368. D_S(struct FileInfoBlock,fib);
  369. if(!ExamineFH(file->af_File,fib))
  370.     {
  371.     AS_RecordSyncFailure(file);
  372.     return FALSE;
  373.     }
  374. *size=fib->fib_Size;
  375. return TRUE;
  376. }
  377.  
  378. LONG __saveds SeekAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,LONG position,LONG mode)
  379. {
  380. LONG current,target,roundTarget,filePos;
  381. LONG minBuf,maxBuf,bytesArrived,diff;
  382. LONG fileSize;
  383. bytesArrived=AS_WaitPacket(file);
  384. if(bytesArrived<0)
  385.     {
  386.     if(file->af_SeekPastEOF)
  387.         {
  388.         bytesArrived=file->af_LastRes1;
  389.         file->af_BytesLeft=file->af_LastBytesLeft;
  390.         }
  391.     else return -1;
  392.     }
  393. if(file->af_ReadMode)
  394.     {
  395.     filePos=Seek(file->af_File,0,OFFSET_CURRENT);
  396.     if(filePos<0)
  397.         {
  398.         AS_RecordSyncFailure(file);
  399.         return -1;
  400.         }
  401.     current=filePos-(file->af_BytesLeft+bytesArrived)+file->af_SeekOffset;
  402.     if(mode==MODE_CURRENT) target=current+position;
  403.     else if(mode==MODE_START) target=position;
  404.     else 
  405.         {
  406.         if(!GetFileSize(file,&fileSize)) return -1;
  407.         target=fileSize+position;
  408.         }
  409.     minBuf=current-(LONG)(file->af_Offset-file->af_Buffers[1-file->af_CurrentBuf]);
  410.     maxBuf=current+file->af_BytesLeft+bytesArrived;
  411.     diff=target-current;
  412.     if((target<minBuf)||(target>=maxBuf))
  413.         {
  414.         if(target>=maxBuf)
  415.             {
  416.             if(!GetFileSize(file,&fileSize)) return -1;
  417.             if(target>fileSize)
  418.                 {
  419.                 file->af_SeekPastEOF=TRUE;
  420.                 SetIoErr(ERROR_SEEK_ERROR);
  421.                 AS_RecordSyncFailure(file);
  422.                 return -1;
  423.                 }
  424.             }
  425.         roundTarget=(target/file->af_BlockSize)*file->af_BlockSize;
  426.         if(Seek(file->af_File,roundTarget-filePos,OFFSET_CURRENT)<0)
  427.             {
  428.             AS_RecordSyncFailure(file);
  429.             return -1;
  430.             }
  431.         AS_SendPacket(file,file->af_Buffers[0]);
  432.         file->af_SeekOffset=target-roundTarget;
  433.         file->af_BytesLeft=0;
  434.         file->af_CurrentBuf=0;
  435.         file->af_Offset=file->af_Buffers[1];
  436.         }
  437.     else if((target<current)||(diff<=file->af_BytesLeft))
  438.         {
  439.         AS_RequeuePacket(file);
  440.         file->af_BytesLeft-=diff;
  441.         file->af_Offset+=diff;
  442.         if(file->af_SeekPastEOF) file->af_Packet.sp_Pkt.dp_Res1=file->af_LastRes1;
  443.         }
  444.     else
  445.         {
  446.         AS_SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);
  447.         diff-=file->af_BytesLeft-file->af_SeekOffset;
  448.         file->af_Offset=file->af_Buffers[file->af_CurrentBuf]+diff;
  449.         file->af_BytesLeft=bytesArrived-diff;
  450.         file->af_SeekOffset=0;
  451.         file->af_CurrentBuf=1-file->af_CurrentBuf;
  452.         }
  453.     }
  454. else
  455.     {
  456.     if(file->af_BufferSize>file->af_BytesLeft)
  457.         {
  458.         if(Write(file->af_File,file->af_Buffers[file->af_CurrentBuf],file->af_BufferSize-file->af_BytesLeft)<0)
  459.             {
  460.             AS_RecordSyncFailure(file);
  461.             return -1;
  462.             }
  463.         }
  464.     current=Seek(file->af_File,position,mode);
  465.     if(current<0)
  466.         {
  467.         AS_RecordSyncFailure(file);
  468.         return -1;
  469.         }
  470.     file->af_BytesLeft=file->af_BufferSize;
  471.     file->af_CurrentBuf=0;
  472.     file->af_Offset=file->af_Buffers[0];
  473.     }
  474. if(file->af_SeekPastEOF) file->af_SeekPastEOF=FALSE;
  475. SetIoErr(0);
  476. return current;
  477. }
  478.  
  479. LONG __saveds WriteAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,APTR buffer,LONG numBytes)
  480. {
  481. LONG totalBytes=0;
  482. if(!file->af_Handler)
  483.     {
  484.     file->af_Offset=file->af_Buffers[0];
  485.     file->af_BytesLeft=file->af_BufferSize;
  486.     return numBytes;
  487.     }
  488. while(numBytes>file->af_BytesLeft)
  489.     {
  490.     if(file->af_BytesLeft)
  491.         {
  492.         copymem(buffer,file->af_Offset,file->af_BytesLeft);
  493.         numBytes-=file->af_BytesLeft;
  494.         buffer=(APTR)((ULONG)buffer+file->af_BytesLeft);
  495.         totalBytes+=file->af_BytesLeft;
  496.         }
  497.     if(AS_WaitPacket(file)<0) return -1;
  498.     AS_SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);
  499.     file->af_CurrentBuf=1-file->af_CurrentBuf;
  500.     file->af_Offset=file->af_Buffers[file->af_CurrentBuf];
  501.     file->af_BytesLeft=file->af_BufferSize;
  502.     }
  503. copymem(buffer,file->af_Offset,numBytes);
  504. file->af_BytesLeft-=numBytes;
  505. file->af_Offset+=numBytes;
  506. return totalBytes+numBytes;
  507. }
  508.  
  509. LONG __saveds WriteCharAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,ULONG ch)
  510. {
  511. UBYTE    c;
  512. if(file->af_BytesLeft)
  513.     {
  514.     *file->af_Offset=ch;
  515.     --file->af_BytesLeft;
  516.     ++file->af_Offset;
  517.     return 1;
  518.     }
  519. c=ch;
  520. return WriteAsyncPPC(base,file,&c,1);
  521. }
  522.  
  523. LONG __saveds WriteLineAsyncPPC(struct AsyncIOBase *base,struct AsyncFile *file,STRPTR line)
  524. {
  525. return WriteAsyncPPC(base,file,line,strlen(line));
  526. }
  527.